Creating Bitmaps Offscreen
The section "Converting Other Types of Shapes to Bitmaps" beginning on page 5-34 describes how you can convert a single QuickDraw GX shape to a bitmap shape. This section shows you how to draw multiple QuickDraw GX shapes to a single bitmap shape.When you draw a shape, QuickDraw GX does the following:
Therefore, to draw shapes into an offscreen bitmap, you need to
- examines the shape's transform object, which contains a view port list
- examines the view ports in this list, each of which belongs to a view group
- examines these view groups, which contain view devices
- decides which view devices the shape actually intersects
- examines these view devices, each of which contains a bitmap
- renders the shape into these bitmaps
You can find complete information about transforms, view devices, view groups, and view ports in the chapters "Transform Objects" and "View-Related Objects" in Inside Macintosh: QuickDraw GX Objects.
- create a bitmap shape to contain the rendered shapes
- create a view group to contain a view device
- create a view device to contain the bitmap shape
- create a view port that belongs to the view group
- create a transform to reference the view port
- associate the transform with the shapes you want to draw offscreen
- clear the offscreen bitmap
- draw the shapes
To create the offscreen bitmap, you must define a shape reference for the bitmap shape and create a bitmap shape of the appropriate size:
gxShape aBitmapShape; aBitmapShape = CreateABitmap(200, 200);Listing 5-12 shows a possible definition for theCreateABitmap
function. This function creates a black-and-white bitmap of a specified height and width.Listing 5-12 Creating a black-and-white bitmap
static gxShape CreateABitmap(long height, long width) { gxShape aBitmapShape; gxBitmap aBitmapGeometry; const gxPoint initialLocation = {ff(0), ff(0)}; aBitmapGeometry.image = nil; aBitmapGeometry.width = width; aBitmapGeometry.height = height; aBitmapGeometry.rowBytes = 0; aBitmapGeometry.pixelSize = 1; aBitmapGeometry.space = gxNoSpace; aBitmapGeometry.set = nil; aBitmapGeometry.profile = nil; aShape = GXNewBitmap(&aBitmapGeometry, &initialLocation); return(aBitmapShape); }To create the offscreen view device, view group, and view port objects, you must declare references to them:
gxViewGroup offscreenViewGroup; gxViewDevice offscreenViewDevice; gxViewPort offscreenViewPort;You create the view group object first:
offscreenViewGroup = GXNewViewGroup();Then you can create the view device and view port objects. To create a view device, you must specify both the view group it belongs to and the bitmap it uses when rendering shapes:
offscreenViewDevice = GXNewViewDevice(offscreenViewGroup, aBitmapShape);To create a view port, you need only specify the view group to which it belongs:
offscreenViewPort = GXNewViewPort(offscreenViewGroup);To draw shapes to this offscreen view port, you need to create a new transform object. First, you must declare a reference to a transform object:
gxTransform offscreenTransform;Then you can create it and set its view port list to contain the offscreen view port:
offscreenTransform = GXNewTransform(); GXSetTransformViewPorts(offscreenTransform, 1, &offscreenViewPort);Now you're ready to draw shapes offscreen. The first shape that you draw is a simple white rectangle, and drawing it initializes the pixels in the offscreen bitmap:
gxShape aRectangleShape; gxRectangle boundsRectangle = {ff(0), ff(0), ff(200), ff(200)}; aRectangleShape = GXNewRectangle(&boundsRectangle); SetShapeCommonColor(aRectangleShape, gxWhite);To draw this white rectangle to the offscreen bitmap, you must set its transform object to be the offscreen transform object:
GXSetShapeTransform(aRectangleShape, offscreenTransform);Then you draw and dispose of the shape:
GXDrawShape(aRectangleShape); GXDisposeShape(aRectangleShape);Since the rectangle shape references the offscreen transform object, QuickDraw GX draws the white rectangle into the offscreen bitmap.Because the offscreen bitmap is now initialized, you can draw other shapes to it. The following code demonstrates how to create a line shape and draw it to the offscreen bitmap:
gxShape aLineShape; gxLine lineGeometry = {ff(40), ff(40), ff(160), ff(160)}; aLineShape = GXNewLine(&lineGeometry); GXSetShapePen(aLineShape, ff(50)); GXSetShapeTransform(aLineShape, offscreenTransform); GXDrawShape(aLineShape); GXDisposeShape(aLineShape);As another example, the following code demonstrates how to create a text shape and draw it to the offscreen bitmap:
gxShape aTextShape; gxPoint textLocation = {ff(70), ff(100)}; gxPoint textCenter; aTextShape = GXNewText(9, (unsigned char *) "123456789", &textLocation) ; GXGetShapeCenter(aTextShape, 0, &textCenter); GXScaleShape(aTextShape, ff(3), ff(3), textCenter.x, textCenter.y); SetShapeCommonTransfer(aTextShape, gxXorMode); GXSetShapeTransform(aTextShape, offscreenTransform); GXDrawShape(aTextShape); GXDisposeShape(aTextShape);This code segment uses theSetShapeCommonTransfer
library function, which is available in the transfer mode library.Finally, to transfer the offscreen bitmap to the screen, you need only draw the bitmap:
GXDrawShape(aBitmapShape);When drawing the offscreen bitmap, QuickDraw GX uses the information in the transform object of the offscreen bitmap shape. This example uses theGXNewBitmap
function to create the offscreen bitmap, and so it references the same transform object as the default bitmap shape. The transform of the default bitmap references the default view port, as described in the chapter "View-Related Objects" in Inside Macintosh: QuickDraw GX Objects. Since the default view port is typically on screen, drawing the offscreen bitmap effectively transfers it to the screen.Listing 5-13 shows the complete sample function to create an offscreen bitmap, draw shapes to it, and copy it to the screen.
Listing 5-13 Creating an offscreen bitmap
void CreateOffscreenBitmap(void) { gxShape aBitmapShape, aRectangleShape, aLineShape, aTextShape; gxRectangle boundsRectangle = {ff(0), ff(0), ff(200), ff(200)}; gxLine lineGeometry = {ff(40), ff(40), ff(160), ff(160)}; gxPoint textLocation = {ff(70), ff(100)}; gxPoint textCenter; /* declare view group, and so forth. */ aBitmapShape = CreateABitmap(200, 200); offscreenViewGroup = GXNewViewGroup(); offscreenViewDevice = GXNewViewDevice(offscreenViewGroup, aBitmapShape); offscreenViewPort = GXNewViewPort(offscreenViewGroup); offscreenTransform = GXNewTransform(); GXSetTransformViewPorts(offscreenTransform, 1, &offscreenViewPort); /* draw white rectangle to clear bitmap */ aRectangleShape = GXNewRectangle(&boundsRectangle); GXSetShapeTransform(aRectangleShape, offscreenTransform); SetShapeCommonColor(aRectangleShape, gxWhite); GXDrawShape(aRectangleShape); GXDisposeShape(aRectangleShape); /* draw thick diagonal line offscreen */ aLineShape = GXNewLine(&lineGeometry); GXSetShapePen(aLineShape, ff(50)); GXSetShapeTransform(aLineShape, offscreenTransform); GXDrawShape(aLineShape); GXDisposeShape(aLineShape); /* draw text offscreen */ aTextShape = GXNewText(9, (unsigned char *) "123456789", &textLocation) ; GXGetShapeCenter(aTextShape, 0, &textCenter); GXScaleShape(aTextShape, ff(3), ff(3), textCenter.x, textCenter.y); SetShapeCommonTransfer(aTextShape, gxXorMode); GXSetShapeTransform(aTextShape, offscreenTransform); GXDrawShape(aTextShape); GXDisposeShape(aTextShape); /* transfer bitmap to screen */ GXDrawShape(aBitmapShape); GXDisposeShape(aBitmapShape); GXDisposeTransform(offscreenTransform); GXDisposeViewGroup(offscreenViewGroup); }Figure 5-29 shows the result of this function.Figure 5-29 Multiple shapes drawn to a bitmap
The offscreen library provided with QuickDraw GX contains some utilities that simplify the creation of offscreen bitmaps. This library defines the
offscreen
structure, which contains a reference to a transform, view port, view device, and view group. Listing 5-14 shows how to use the offscreen library to create the bitmap shown in Figure 5-29 .Listing 5-14 Creating an offscreen bitmap using the offscreen library
void CreateOffscreenBitmap(void) { shape aBitmapShape, aRectangleShape, aLineShape, aTextShape; offscreen anOffscreen; const gxRectangle boundsRectangle = {ff(0), ff(0), ff(200), ff(200)}; const gxLine lineGeometry = {ff(40), ff(40), ff(160), ff(160)}; const gxPoint textLocation = {ff(70), ff(100)}; gxPoint textCenter; aBitmapShape = CreateABitmap(200, 200); /* create all offscreen-related objects */ CreateOffscreen(&anOffscreen, aBitmapShape); aRectangleShape = GXNewRectangle(&boundsRectangle); GXSetShapeTransform(aRectangleShape, anOffscreen.xform); SetShapeCommonColor(aRectangleShape, gxWhite); GXDrawShape(aRectangleShape); GXDisposeShape(aRectangleShape); aLineShape = GXNewLine(&lineGeometry); GXSetShapePen(aLineShape, ff(50)); GXSetShapeTransform(aLineShape, anOffscreen.xform); GXDrawShape(aLineShape); GXDisposeShape(aLineShape); aTextShape = GXNewText(9, (unsigned char *) "123456789", &textLocation) ; GXGetShapeCenter(aTextShape, 0, &textCenter); GXScaleShape(aTextShape, ff(3), ff(3), textCenter.x, textCenter.y); SetShapeCommonTransfer(aTextShape, gxXorMode); GXSetShapeTransform(aTextShape, anOffscreen.xform); GXDrawShape(aTextShape); GXDisposeShape(aTextShape); GXDrawShape(aBitmapShape); GXDisposeShape(aBitmapShape); /* dispose of all offscreen-related objects */ DisposeOffscreen(&anOffscreen); GXDrawShape(aBitmapShape); GXDisposeShape(aBitmapShape); }
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help